package com.learning.optimize.jdk.proxy.cglib;

import com.learning.optimize.jdk.proxy.aop.Advice;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * ClassName: CglibProxy
 * Description:
 * Date: 2018/7/25 10:03 【需求编号】
 *
 * @author Sam Sho
 * @version V1.0.0
 */
public class CglibProxy {

    public static void main(String[] args) {

        test();
    }

    static void test() {

        // 被代理类
        CglibTarget cglibTarget = new CglibTarget();

        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(cglibTarget.getClass());
        enhancer.setCallback(new MethodInterceptor() {
            @Override
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                System.out.println("方法调用前");

                System.out.println("proxy.getClass().getName()：" + proxy.getClass().getName());
                System.out.println("method.getName()：" + method.getName());

                //代理类调用父类的方法
                Object object = methodProxy.invoke(proxy, args);
                System.out.println("方法调用返回的值：" + object);

                System.out.println("方法调用后");
                return object;
            }
        });

        CglibTarget target = (CglibTarget) enhancer.create();

        target.first();

        /*
            方法调用前
            proxy.getClass().getName()：com.learning.optimize.jdk.proxy.cglib.CglibTarget$$EnhancerByCGLIB$$b310c297
            method.getName()：first
            first 方法被调用
            方法调用返回的值：null
            方法调用后
         */
    }


    public static Object getCgProxy(final Object targrt, final Advice advice) {

        //利用cglib 中的Enhancer
        Enhancer enhancer = new Enhancer();

        //把目标类设置为代理的父类(继承目标类，覆盖其所有非final的方法)
        enhancer.setSuperclass(targrt.getClass());

        //设置回调， //实现MethodInterceptor 接口
        enhancer.setCallback(new MethodInterceptor() {

            @Override
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                Object object = null;
                try {
                    //前置
                    advice.before(method);
                    object = methodProxy.invoke(targrt, args);
                    //后置
                    advice.after(method);
                } catch (Exception e) {
                    //例外，异常
                    advice.afterThrow(method);
                } finally {
                    //最终
                    advice.afterFinally(method);
                }

                return object;
            }
        });

        return enhancer.create();
    }
}
